/*
 * lattice.h
 *
 *  Created on: 2014-4-11
 *      Author: Kise
 */

#ifndef LATTICE_H_
#define LATTICE_H_

#include <stdio.h>
#include <string.h>  /* for strlen */
#include "gb2312.h"

#ifdef __cplusplus
extern "C" {
#endif

/* 
 * HZK16 汉字库中，每个汉字由 16 * 16的点阵来表示，因此表示一个汉字需要256个点
 * 字库数据中的每个字节的每一位都表示点阵中的一个点的二值（0或1）
 * 因此完全表示一个16 × 16的点阵需要32个字节(256bit)
 */

#define HZK16_ROW 16           /* 点阵共有16行 */
#define HZK16_COL 16           /* 点阵共有16列 */
#define HZK16_BYTE_PER_ROW 2   /* 每行用2个byte的数据来表示 */
#define HZK16_BYTE_PER_CHAR 32 /* 每个字符的点阵数据是32个字节 */

#define ASC16_ROW 16
#define ASC16_COL 8
#define ASC16_BYTE_PER_ROW 1
#define ASC16_BYTE_PER_CHAR 16

/*
 * @brief	初始化汉字及ASC码的点阵数据,在调用offset和get等函数时必须先调用该函数
 * @param	hzk16 是汉字库的文件路径, asc16 是ASC字符库的文件路径
 * @return	成功返回0， 失败返回-1
 */
int lattice16_init(const char *hzk16, const char *asc16);

/*
 * @brief	获取汉字在点阵字库中对应的点阵数据
 * @param	ch: 是一个以GB2312编码的两字节汉字
 * @param	lattice: 作为出参，用来存放点阵数据
 * @return	获取成功则返回0，且点阵数据存放在lattice中，失败返回-1，lattice中内容不确定
 */
int hzk16_get(const struct gb2312_char *ch, char lattice[HZK16_BYTE_PER_CHAR]);

/*
 * @brief	获取ASC字符ch在点阵字库中对应的点阵数据
 * @param	lattice: 作为出参，用来存放点阵数据
 * @return	获取成功则返回0，且点阵数据存放在lattice中，失败返回-1，lattice中内容不确定
 */
int asc16_get(unsigned char ch, char lattice[ASC16_BYTE_PER_CHAR]);

typedef void (*lattice_callback)(int row, int col, int seted, void *arg);

/*
 * @brief	对点阵中每一个被设置的点,调用回调函数cb
 * @param	lattice32: 是表示某个汉字点阵的32字节数据, arg是要传给cb的参数
 */
void hzk_foreach(const char *lattice32, lattice_callback cb, void *arg);

/*
 * @brief	对点阵中每一个被设置的点,调用回调函数cb
 * @param	lattice16: 是表示某个ASC字符点阵的32字节数据, arg是要传给cb的参数
 */
void asc_foreach(const char *lattice16, lattice_callback cb, void *arg);

/*-----以下函数将点阵打印到屏幕上，演示了foreach函数的用法--------*/

static inline void my_print(int row, int col, int seted, void *arg)
{
	if (col == 0 && row != 0)
		printf("\n");

	printf("%s", seted ? "0" : "_");
}

static inline void hzk16_print(const char *lattice32)
{
	hzk_foreach(lattice32, my_print, NULL);
	printf("\n");
}

static inline void asc16_print(const char *asc16)
{
	asc_foreach(asc16, my_print, NULL);
	printf("\n");
}

/*
 * @brief	将一串以GB2312编码的字符串打印到屏幕上
 */
static inline void gb2312_print(const unsigned char *gb2312)
{
	size_t len = strlen((const char*) gb2312);
	const unsigned char *ptr;

	char latc_hzk[HZK16_BYTE_PER_CHAR];
	char latc_asc[ASC16_BYTE_PER_CHAR];

	for (ptr = gb2312; ptr < (gb2312 + len);) {
		// 魔数0x7F（127）是ACS编码的上限，其余的都当作GB2312的第一个字节
		if (*ptr <= 0x7F) {
			if (0 == asc16_get(*ptr, latc_asc))
				asc16_print(latc_asc);
			ptr++;
		} else {
			// printf("hanzi : %.2x %.2x\n", *ptr, *(ptr + 1));
			if (0 == hzk16_get((struct gb2312_char*) ptr, latc_hzk))
				hzk16_print(latc_hzk);
			ptr += 2;
		}
	}
}

#ifdef __cplusplus
}
#endif

#endif /* LATTICE_H_ */
